<?php
/**
 * @author spenceryg
 * @date 2023/3/15
 * @time 6:10 下午
 * @focus love & life
 */


namespace app\common\lib;


use app\common\lib\verify\AliSmsVerify;
use app\common\lib\verify\VerifyFactory;
use app\common\model\ApikeyLibrary;
use app\common\model\BaiduToken;
use app\common\model\GptToken;
use GuzzleHttp\Client;
use Orhanerday\OpenAi\OpenAi;
use think\facade\Log;

class ChatGptBaidu
{

    public static function chatSocket($msg, $connection, $returnLine = false)
    {


        $client = new Client([
            // Base URI is used with relative requests
            'base_uri' => config('transfer.python_address'),
            'timeout' => 80,
        ]);

        try {
            $tokenModel = BaiduToken::order('update_time', 'asc')->where('id', '>', 0)->find();
            $tokenModel->force()->save();

            $res = $client->request('post', '/baidu_chat', [
                'stream' => true,
                'verify' => false,
                'json' => [
                    'query' => $msg,
                    "ak"=>$tokenModel->ak,
                    "sk"=> $tokenModel->sk
                ],
            ]);

        } catch (\Exception $e) {
            $msg = $e->getResponse()->getReasonPhrase();
            $connection->send(
                json_encode([
                    'type' => 'chat',
                    'content' =>  $msg
            ])
            );
        }


        $body = $res->getBody();
        $remainder = '';
        $all_res = '';
        while (!$body->eof()) {
            $chunk = $body->read(2);

            // 合并剩余的字符和当前的数据块
            $chunk = $remainder . $chunk;


            // 处理完整的字符
            while (mb_strlen($chunk, 'UTF-8') > 1) {
                $char = mb_substr($chunk, 0, 1, 'UTF-8');
                // 处理每个字符，比如输出或者其他操作
                $connection->send(
                    json_encode([
                        'type' => 'chat',
                        'content' =>  $char
                    ])
                );
                $all_res .= $char;
                // 移除已处理的字符
                $chunk = mb_substr($chunk, 1, null, 'UTF-8');
            }

            // 存储剩余的字符
            $remainder = $chunk;

        }

        $connection->send(
            json_encode([
                'type' => 'chat',
                'content' =>  $remainder
            ])
        );

        $all_res .= $remainder;
        return $all_res;
    }

    public static function chat($msg, $stream = false, $event_name = '', $returnLine = true, $event_handle = false,$is_json = true)
    {
        $client = new Client([
            // Base URI is used with relative requests
            'base_uri' => config('transfer.python_address'),
            'timeout' => 80,
        ]);

//        $token = GptToken::where('id' ,'=', 1)->value('token');
        $tokenModel = GptToken::order('update_time', 'asc')->where('id', '>', 0)->find();
        $token = $tokenModel['token'];
        $tokenModel->force()->save();


        header('X-Accel-Buffering: no');
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');

        //跨域
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type');

        set_time_limit(0); //防止超时
        ob_end_clean();
        ob_implicit_flush(1);



        try {
            $tokenModel = BaiduToken::order('update_time', 'asc')->where('id', '>', 0)->find();
            $tokenModel->force()->save();

            $res = $client->request('post', '/baidu_chat', [
                'stream' => true,
                'verify' => false,
                'json' => [
                    'query' => $msg,
                    "ak"=>$tokenModel->ak,
                    "sk"=> $tokenModel->sk
                ],
            ]);

        } catch (\Exception $e) {
            $msg = $e->getResponse()->getReasonPhrase();
            $c = "event:{$event_name}" . PHP_EOL; //定义事件
            $c .= "data:" . $msg . PHP_EOL; //推送内容
            echo $c . PHP_EOL;

            $c = "event:{$event_name}" . PHP_EOL; //定义事件
            $c .= "data:end" . PHP_EOL; //推送内容
            echo $c . PHP_EOL;
        }


        $body = $res->getBody();
        $remainder = '';
        $all_res = '';
        while (!$body->eof()) {
            $chunk = $body->read(2);

            // 合并剩余的字符和当前的数据块
            $chunk = $remainder . $chunk;

            // 处理完整的字符
            while (mb_strlen($chunk, 'UTF-8') > 1) {
                $char = mb_substr($chunk, 0, 1, 'UTF-8');
                // 处理每个字符，比如输出或者其他操作
                $c = "event:{$event_name}" . PHP_EOL; //定义事件
                $this_str_json = [
                    'title' => $char,
                ];
                $c .= "data:" . json_encode($this_str_json) . PHP_EOL; //推送内容
                $all_res .= $char;
                echo $c . PHP_EOL;
                // 移除已处理的字符
                $chunk = mb_substr($chunk, 1, null, 'UTF-8');
            }

            // 存储剩余的字符
            $remainder = $chunk;

        }

        $c = "event:{$event_name}" . PHP_EOL; //定义事件
        $this_str_json = [
            'title' => $remainder,
        ];
        $c .= "data:" . json_encode($this_str_json) . PHP_EOL; //推送内容
        echo $c . PHP_EOL;

        $all_res .= $remainder;

        $c = "event:{$event_name}" . PHP_EOL; //定义事件
        $c .= "data:end" . PHP_EOL; //推送内容
        echo $c . PHP_EOL;

        return $all_res;


    }

    public static function getTitles($query): array
    {
        $res = self::chat($query);
        $arr = explode("\n", trim($res));
        $res = [];
        foreach ($arr as $item) {
            $res[] = explode(' ', $item, 2)[1];
        }
        return $res;
    }

    public static function sendEvent($event_name, $key)
    {
        Log::channel('title')->info($key);
        $res = '';
        $arr = explode(' ', trim($key), 2);
        if(sizeof($arr) == 2) {
            $key = $arr[1];
        }else{
            $key = $arr[0];
        }
        $data = [
            'title' => $key,
            'is_used' => 0
        ];
        $res = $res . "event:{$event_name}" . PHP_EOL;
        $res = $res . "data:" . json_encode($data) . PHP_EOL;
        echo $res . PHP_EOL;
    }


    public static function sendEventIsUsed($event_name, $key)
    {
        $res = '';
        $key = explode(' ', $key, 2)[1];
        $data = [
            'title' => $key,
            'is_used' => 0
        ];
        $res = $res . "event:{$event_name}" . PHP_EOL;
        $res = $res . "data:" . json_encode($data) . PHP_EOL;
        echo $res . PHP_EOL;
    }
}
